`timescale 1ns/1ps
module SecurityDoor(PME, PM, PC, PCE, RC, RCE, RME, CS, DOC, T, D, clk, rst, GLED, RLED, A, MO, Ac);
input PME;             //Program Mode Enable: 1 enables the mode to be programmed, 0 does not enable the mode to be programmed
input [1:0] PM;     //Program Mode: 00 = access for all times, 01 = allows access from 7am-12pm and all times with credentials,
                    // 10 = allow access weekdays from 7am-12pm and all times with cred., 11 = allow access with cred. only
input [23:0] PC;     //Program Credential: the credential
input PCE;             //Program Credential Enable:
input [23:0] RC;     //Remove Credential:
input RCE;             //Remove Credential Enable:
input RME;             //Return Memory Enable:
input [23:0] CS;     //Card Swipe:
input DOC;             //Door Open or Close: 0 = door closed 1 = door opened
input [11:0] T;     //Time of day:
input [2:0] D;         //Day of the week:
input clk;             //clock:
input rst;             //reset: low enable
output GLED;         //Green LED:
output RLED;         //Red LED:
output A;             //Alarm:
output [23:0] MO;    //Memory Output:
output Ac;             //Access:

wire rst;
wire clk;
wire PME;
wire [1:0] PM;
wire [23:0] PC;
wire PCE;
wire [23:0] RC;
wire RCE;
wire [23:0] CS;
wire DOC;
wire [11:0] T;
wire [2:0] D;
wire A;
reg Ac;
reg [23:0] MO;
reg GLED;
reg RLED;

reg tPass;
reg dPass;
reg [1:0] currentPM;
reg [23:0] mem [99:0];

wire tPass_wire;
wire dPass_wire;
wire currentPM_wire;
wire dayTimePass;
wire Access_wire;
wire AccessNot;
wire cardSwipe_wire;
wire cardSwipePass_wire;
wire found_null_wire;
reg [7:0] i;
reg Access;
reg cardSwipe;
reg cardSwipePass;
reg found_null;

assign tPass_wire = tPass;
assign dPass_wire = dPass;
assign currentPM_wire = currentPM;
assign cardSwipe_wire = cardSwipe;
assign Access_wire = Access;
assign found_null_wire = found_null;

and a0(dayTimePass, tPass_wire, dPass_wire);
not n0(AccessNot, Access_wire);
and a1(A, AccessNot, DOC);

always @ (posedge clk or negedge rst) begin
    if(rst == 1'b0) begin
        currentPM <=2'b00;
        for(i = 0; i < 100; i = i + 1) begin
            mem[i] <= 24'b111111111111111111111111;
        end
        i = 0;
        found_null = 1'b0;
    end else begin
        //if program mode enable is high
        if(PME == 1'b1) begin
            currentPM <= PM;
        end else begin
            currentPM <= currentPM;
        end
        
        //if program credential enable is high
        if(PCE == 1'b1) begin
            for(i = 0; i < 100; i = i + 1) begin
              if(found_null_wire == 1'b0) begin
                if(mem[i] == 24'b111111111111111111111111) begin
                  mem[i] <= PC;
                  found_null <= 1'b1;
                end
              end else begin
                //do nothing
              end
            end
            found_null <= 1'b0;
        end else begin
            //do nothing
        end
        
        //if remove credential enable is high
        if(RCE == 1'b1) begin
            for(i = 0; i < 100; i = i + 1) begin
                if(mem[i] == RC) begin
                  mem[i] <= 24'b111111111111111111111111;
                end else begin
                  //do nothing
                end
            end
            i = 0;
        end else begin
            //do nothing
        end
        
        //if cardswipe is not the reserved "null" value
        if(CS != 24'b111111111111111111111111) begin
            cardSwipe <= 1'b1;
            cardSwipePass <= 1'b0;
            for(i = 0; i < 100; i = i + 1) begin
                if(mem[i] == CS) begin
                    cardSwipePass <= 1'b1;
                end else begin
                    //do nothing
                end
            end
            i = 0;
        end else begin
            cardSwipe <= 1'b0;
            cardSwipePass <= 1'b0;
        end
        
        //if return memory enable is high
        if(RME == 1'b1) begin
            for(i = 0; i < 100; i = i + 1) begin
                MO <= mem[i];
            end
            i = 0;
        end else begin
            //do nothing
        end
    end
end

//day compare, does not require the clock
always @ (*) begin
    if(currentPM_wire == 2'b01) begin
        dPass <= 1'b1;
    end else if(currentPM_wire == 2'b10) begin
        if(D < 3'b110) begin
            dPass <= 1'b1;
        end else begin
            dPass <= 1'b0;
        end
    end else begin
        dPass <= 1'b1;
    end
end

//time compare, again does not require the clock
always @ (*) begin
    if(700 <= T <= 1200) begin
        tPass <= 1'b1;
    end else begin
        tPass <= 1'b0;
    end
end

//multiplexor for the value of Access
always @ (*) begin
  Ac <= Access_wire;
    if(currentPM_wire == 2'b00) begin
        Access <= 1'b1;
    end else if(currentPM_wire == 2'b01) begin
        Access <= dayTimePass || cardSwipePass_wire; 
    end else if(currentPM_wire == 2'b10) begin
        Access <= dayTimePass || cardSwipePass_wire;
    end else if(currentPM_wire == 2'b11) begin
        Access <= cardSwipePass_wire;
    end else begin
      //do nothing
    end
      
end

always @ (posedge cardSwipe_wire) begin
    GLED <= 1'b0;
    RLED <= 1'b0;
    if(Access_wire == 1'b0) begin
        RLED <= 1'b1;
        GLED <= 1'b0;
    end else begin
        GLED <= 1'b1;
        RLED <= 1'b0;
    end
end

endmodule
